package utils

import (
	"encoding/hex"
	"fmt"
	"net"
	"strconv"
	"strings"
	"unicode"
)

// IPAddr 表示IP地址和端口
type IPAddr struct {
	IP   net.IP
	Port uint16
}

// NewIPAddr 创建新的IP地址
func NewIPAddr(ip net.IP, port uint16) *IPAddr {
	return &IPAddr{
		IP:   ip,
		Port: port,
	}
}

// String 返回IP地址的字符串表示
func (ip *IPAddr) String() string {
	return fmt.Sprintf("%s:%d", ip.IP.String(), ip.Port)
}

// Equal 比较两个IP地址是否相等
func (ip *IPAddr) Equal(other *IPAddr) bool {
	return ip.IP.Equal(other.IP) && ip.Port == other.Port
}

// Toolkit 工具包
type Toolkit struct{}

// NewToolkit 创建新的工具包实例
func NewToolkit() *Toolkit {
	return &Toolkit{}
}

// Ascii2Hex 将ASCII字符串转换为十六进制
func (tk *Toolkit) Ascii2Hex(src string) (string, []int, int) {
	var result strings.Builder
	var positions []int
	count := 0

	for i, char := range src {
		if char < 32 || char > 126 {
			// 非ASCII字符，转换为十六进制
			result.WriteString(fmt.Sprintf("%02X", char))
			positions = append(positions, i)
			count++
		} else {
			// ASCII字符，保持原样
			result.WriteRune(char)
		}
	}

	return result.String(), positions, count
}

// Bin2Hex 将二进制数据转换为十六进制字符串
func (tk *Toolkit) Bin2Hex(data []byte) string {
	return strings.ToUpper(hex.EncodeToString(data))
}

// Bin2Ascii 将二进制数据转换为ASCII字符串
func (tk *Toolkit) Bin2Ascii(data []byte) string {
	var result strings.Builder

	for _, b := range data {
		if b >= 32 && b <= 126 {
			result.WriteByte(b)
		} else {
			result.WriteString(fmt.Sprintf("\\x%02X", b))
		}
	}

	return result.String()
}

// Hex2Bin 将十六进制字符串转换为二进制数据
func (tk *Toolkit) Hex2Bin(src string) ([]byte, error) {
	// 移除空格和换行符
	src = strings.ReplaceAll(src, " ", "")
	src = strings.ReplaceAll(src, "\n", "")
	src = strings.ReplaceAll(src, "\r", "")

	// 确保字符串长度为偶数
	if len(src)%2 != 0 {
		src = "0" + src
	}

	return hex.DecodeString(src)
}

// Ascii2Bin 将ASCII字符串转换为二进制数据
func (tk *Toolkit) Ascii2Bin(src string) ([]byte, error) {
	// 处理转义序列
	var result []byte

	for i := 0; i < len(src); i++ {
		if src[i] == '\\' && i+1 < len(src) {
			switch src[i+1] {
			case 'x', 'X':
				// 十六进制转义
				if i+3 < len(src) {
					hexStr := src[i+2 : i+4]
					if val, err := strconv.ParseUint(hexStr, 16, 8); err == nil {
						result = append(result, byte(val))
						i += 3
						continue
					}
				}
			case 'n':
				result = append(result, '\n')
				i++
				continue
			case 'r':
				result = append(result, '\r')
				i++
				continue
			case 't':
				result = append(result, '\t')
				i++
				continue
			}
		}
		result = append(result, src[i])
	}

	return result, nil
}

// SocketTypeName 返回套接字类型名称
func (tk *Toolkit) SocketTypeName(isTCP bool) string {
	if isTCP {
		return "TCP"
	}
	return "UDP"
}

// GetNetworkInterfaces 获取网络接口列表
func (tk *Toolkit) GetNetworkInterfaces() ([]string, error) {
	interfaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}

	var result []string
	for _, iface := range interfaces {
		if iface.Flags&net.FlagUp != 0 && iface.Flags&net.FlagLoopback == 0 {
			addrs, err := iface.Addrs()
			if err != nil {
				continue
			}

			for _, addr := range addrs {
				if ipnet, ok := addr.(*net.IPNet); ok {
					if ipnet.IP.To4() != nil {
						result = append(result, ipnet.IP.String())
					}
				}
			}
		}
	}

	return result, nil
}

// ParseIPAddr 解析IP地址字符串
func (tk *Toolkit) ParseIPAddr(addr string) (*IPAddr, error) {
	host, portStr, err := net.SplitHostPort(addr)
	if err != nil {
		return nil, err
	}

	ip := net.ParseIP(host)
	if ip == nil {
		return nil, fmt.Errorf("无效的IP地址: %s", host)
	}

	port, err := strconv.ParseUint(portStr, 10, 16)
	if err != nil {
		return nil, fmt.Errorf("无效的端口号: %s", portStr)
	}

	return &IPAddr{
		IP:   ip,
		Port: uint16(port),
	}, nil
}

// FormatIPAddr 格式化IP地址
func (tk *Toolkit) FormatIPAddr(ip net.IP, port uint16) string {
	return fmt.Sprintf("%s:%d", ip.String(), port)
}

// IsValidPort 检查端口号是否有效
func (tk *Toolkit) IsValidPort(port string) bool {
	if port == "" {
		return false
	}

	portNum, err := strconv.ParseUint(port, 10, 16)
	if err != nil {
		return false
	}

	return portNum > 0 && portNum <= 65535
}

// IsValidIP 检查IP地址是否有效
func (tk *Toolkit) IsValidIP(ip string) bool {
	return net.ParseIP(ip) != nil
}

// IsValidHost 检查主机地址是否有效
func (tk *Toolkit) IsValidHost(host string) bool {
	// 检查是否为IP地址
	if tk.IsValidIP(host) {
		return true
	}

	// 检查是否为域名
	if len(host) > 0 && len(host) <= 253 {
		for _, char := range host {
			if !unicode.IsLetter(char) && !unicode.IsDigit(char) && char != '.' && char != '-' {
				return false
			}
		}
		return true
	}

	return false
}

// FormatBytes 格式化字节数
func (tk *Toolkit) FormatBytes(bytes int64) string {
	const (
		KB = 1024
		MB = KB * 1024
		GB = MB * 1024
		TB = GB * 1024
	)

	switch {
	case bytes >= TB:
		return fmt.Sprintf("%.2f TB", float64(bytes)/TB)
	case bytes >= GB:
		return fmt.Sprintf("%.2f GB", float64(bytes)/GB)
	case bytes >= MB:
		return fmt.Sprintf("%.2f MB", float64(bytes)/MB)
	case bytes >= KB:
		return fmt.Sprintf("%.2f KB", float64(bytes)/KB)
	default:
		return fmt.Sprintf("%d 字节", bytes)
	}
}

// FormatSpeed 格式化传输速度
func (tk *Toolkit) FormatSpeed(bytesPerSecond float64) string {
	return fmt.Sprintf("%s/s", tk.FormatBytes(int64(bytesPerSecond)))
}

// IsPrintable 检查字符是否可打印
func (tk *Toolkit) IsPrintable(char rune) bool {
	return unicode.IsPrint(char) && char != unicode.ReplacementChar
}

// CountPrintable 统计可打印字符数量
func (tk *Toolkit) CountPrintable(data []byte) int {
	count := 0
	for _, b := range data {
		if tk.IsPrintable(rune(b)) {
			count++
		}
	}
	return count
}
